#!/bin/bash
# ********************************************************************
# 试验环境：CentOS 7.x
# Date: 2025-05-06
# Description：How I SetUp New CentOS7.x System eg:关闭SELinux、配置阿里云yum源、安装基础工具、优化系统设置、升级内核版本等
# author Gavin
# email: lushuan2071@126.com
# command: sh init_centos7_initialize.sh|tee  init_centos7_initialize.log
# ********************************************************************


# 检查是否为root用户
if [ $(id -u) -ne 0 ]; then
    echo "错误：必须使用root权限执行此脚本！"
    exit 1
fi

# 检查网络连通性，需要连接外网
check_internet_connection() {
    # 主执行逻辑
    echo -e "\n >>>> 正在检查系统网络连接..."
    # 定义要测试的多个可靠网站（避免单个网站不可用导致误判）
    TEST_URLS=(
        "http://www.google.com"
        "http://www.baidu.com"
        "http://www.aliyun.com"
        "http://www.163.com"
    )

    local any_success=0

    for url in "${TEST_URLS[@]}"; do
        # 使用curl测试连接，设置超时3秒
        if curl --connect-timeout 3 -s --head "$url" >/dev/null; then
            echo "[网络检查] 成功连接到: $url"
            any_success=1
            break
        else
            echo "[网络检查] 无法连接到: $url (尝试下一个)"
        fi
    done

    if [ "$any_success" -eq 0 ]; then
        echo "错误：系统无法连接任何外部网络！"
        echo "可能原因:"
        echo "1. 网络配置错误"
        echo "2. 防火墙阻止"
        echo "3. DNS设置问题"
        echo "4. 代理配置问题"

        # 尝试诊断具体原因
        echo -e "\n诊断信息:"
        echo "1. 检查网关:"
        ip route show default 2>/dev/null || echo "  未找到默认路由"

        echo "2. 检查DNS解析:"
        nslookup www.baidu.com 2>/dev/null || echo "  DNS解析失败"

        echo "3. 检查ICMP连通性:"
        ping -c 2 8.8.8.8 2>/dev/null || echo "  无法ping通外部IP"

        exit 1
    fi

  # 如果能执行到这里，说明网络正常
  echo "网络连接正常，继续执行脚本..."
  # 在这里添加你的后续脚本内容

  # 示例：显示网络信息
  echo -e "\n当前网络信息:"
  ip addr show | grep -w "inet" | grep -v "127.0.0.1"
  echo "默认网关: $(ip route show default | awk '{print $3}')"
}

# 检查操作系统主版本是否为7
function check() {
  echo -e "\n >>>> 检查操作系统主版本是否为7..."
  # 检查是否为 CentOS 系统
  if [ ! -f /etc/centos-release ]; then
      echo "错误：此脚本仅支持 CentOS 系统。"
      exit 1
  fi

  # 提取 CentOS 主版本号
  CENTOS_VERSION=$(grep -oP '(?<=release )\d+' /etc/centos-release)

  # 检查主版本是否为 7
  if [ "$CENTOS_VERSION" != "7" ]; then
      echo "错误：此脚本仅支持 CentOS 7，当前版本是 CentOS $CENTOS_VERSION。"
      exit 1
  fi

  echo "检测通过：当前系统是 CentOS 7。"
  # 在这里继续您的脚本逻辑...
}


# 配置域名服务器解析
function config_dns_resolv() {
  echo -e "\n >>>> 配置域名服务器解析..."
  # 中国移动域名服务器
  echo -e "nameserver 218.201.4.3\nnameserver 218.201.17.2" >> /etc/resolv.conf
  # ali域名服务器
  echo -e "nameserver 223.5.5.5\nnameserver 223.6.6.6" >> /etc/resolv.conf
  # 谷歌等常用域名服务器
  echo -e "nameserver 1.1.1.1\nnameserver 1.2.4.8\nnameserver 8.8.8.8" >> /etc/resolv.conf
}

# 设置会话连接超时时间和History历史记录配置
function config_session_timeout() {
echo -e "\n >>>> 设置会话连接超时时间和History历史记录配置..."

cat >> /etc/profile <<EOF

export TMOUT=2800
export HISTTIMEFORMAT="%F %T whoami "
EOF
}

# 关闭SELinux（需要重启生效）
function close_SELinux() {
  echo -e "\n >>>> 关闭SELinux..."
  sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  setenforce 0 2>/dev/null
}

# config yum
function config_yum() {
  echo -e "\n >>>> 配置yum 源..."
  # 备份原yum源
  echo "备份原yum源..."
  mkdir -p /etc/yum.repos.d/backup
  mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/ 2>/dev/null

# 配置阿里云yum源
echo "配置阿里云yum源..."
cat > /etc/yum.repos.d/CentOS-Base.repo << 'EOF'
[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-$releasever - Updates - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
baseurl=https://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7

[epel]
name=EPEL for centos7
baseurl=https://mirrors.aliyun.com/epel/7/$basearch/
gpgcheck=0
EOF

  # 清理并重建yum缓存
  echo "重建yum缓存..."
  yum -y update  #  会对系统进行一系列重要变更，日常谨慎执行
  yum clean all >/dev/null
  yum makecache fast >/dev/null

}

# install common tools
function install_common_tools() {
  echo -e "\n >>>> 安装常用工具..."
yum install -y \
    vim \
    wget \
    curl \
    lsof \
    net-tools \
    telnet \
    tree \
    htop \
    iftop \
    iotop \
    unzip \
    rsync \
    chrony \
    lrzsz \
    python3 \
    git \
    zip \
    tcpdump \
    bash-completion \
    bind-utils
}



# time_chronyd
function time_chronyd() {
  echo -e "\n >>>> 配置时间同步..."
  yum install -y chrony
  systemctl enable chronyd
  systemctl start chronyd
  chronyc sources -v
}

# close firewalld
function close_firewalld() {
  echo -e "\n >>>> 关闭防火墙..."
  systemctl stop firewalld
  systemctl disable firewalld
}



# Optimize system parameters
function optimize_system_parameters() {
  echo -e "\n >>>> 优化系统参数..."

  # 禁用Ctrl+Alt+Del重启
  sed -i 's/^#CtrlAltDelButton=/CtrlAltDelButton=/' /etc/systemd/system.conf
  # 禁用空密码登录
  sed -i 's/#PermitEmptyPasswords no/PermitEmptyPasswords no/' /etc/ssh/sshd_config
  # 历史命令添加时间戳
  echo 'export HISTTIMEFORMAT="%F %T "' >> /etc/profile
}



function update_files_limits() {
  echo -e "\n >>>> 设置文件打开数限制..."

cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
EOF

}

function update_PS1() {
  echo -e "\n >>>> 修改终端时间显示..."

  echo 'export PS1="[\u@\h \W]<\D{%Y%m%d %H:%M:%S}>\$ "' >> ~/.bashrc
  source ~/.bashrc  # 立即生效
}

# 关闭不常用的服务
function close_uncommon_used_service() {
  echo -e "\n >>>> 关闭不常用的服务..."
  # 邮件传输代理
  systemctl stop 'postfix'
  systemctl disable 'postfix'
  # 传统网络管理服务，已被network 代替
  systemctl stop 'NetworkManager'
  systemctl disable 'NetworkManager'
  # 自动错误报告工具
  systemctl disable 'abrt-ccpp'
}

# 内核优化
function kernel_optimizations() {
    echo -e "\n >>>> 内核优化..."

cat > /etc/sysctl.d/99-optimize.conf << 'EOF'
# 内存相关
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# 文件描述符
fs.file-max = 131072

# TCP优化
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_max_tw_buckets = 2000000

# 网络队列
net.core.netdev_max_backlog = 3072

# 端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 重试次数
net.ipv4.tcp_retries1 = 2
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2

# 安全设置
net.ipv4.tcp_syncookies = 1
kernel.panic = 10

#防止防火墙iptables报错table full, dropping packet，提升
net.netfilter.nf_conntrack_max = 6553500
#net.netfilter.nf_conntrack_buckets = 100000
net.netfilter.nf_conntrack_tcp_timeout_established = 600

fs.file-max = 4194304
fs.nr_open = 4194304

#LVS arp real server 设置
net.ipv4.ip_forward = 1
#net.ipv4.conf.lo.arp_ignore = 1
#net.ipv4.conf.lo.arp_announce = 2
#net.ipv4.conf.all.arp_ignore = 1
#net.ipv4.conf.all.arp_announce = 2

#修改swap内存使用条件为0，尽可能减少系统对swap使用
vm.swappiness = 0
EOF

# 应用配置
sysctl -p /etc/sysctl.d/99-optimize.conf
}

# 升级内核版本至5.4，这里建议手动操作
function upgrade_kernel_version() {
  echo -e "\n >>>> 升级内核版本至5.4 ..."
  # 生产环境升级内核前先备份
  mkdir /backup && cp -r /etc/{sysctl.conf,security,ssh} /backup
  # 检查当前内核版本
  uname -sr
  # 安装 ELRepo 仓库
  # 导入 ELRepo 公钥
  rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
  # 安装 ELRepo 仓库，这里要检查下 elrepo.repo 下的 elrepo-kernel 源 enabled 是否开启
  yum install -y https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
  # 修改后重新生成缓存
  yum clean all && yum makecache fast

  # 在线安装
  #  查看可用的内核版本，如果没有则选择离线安装
  yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
  # 安装长期支持版内核 (5.4)
  yum --enablerepo=elrepo-kernel install -y kernel-lt

  # 离线安装 https://mirrors.coreix.net/elrepo-archive-archive/kernel/el7/x86_64/RPMS/
  mkdir /tmp/kernel-lt-5.4 && cd /tmp/kernel-lt-5.4 && yum install wget perl -y
  wget https://mirrors.coreix.net/elrepo-archive-archive/kernel/el7/x86_64/RPMS/kernel-lt-5.4.203-1.el7.elrepo.x86_64.rpm
  wget https://mirrors.coreix.net/elrepo-archive-archive/kernel/el7/x86_64/RPMS/kernel-lt-devel-5.4.203-1.el7.elrepo.x86_64.rpm
  wget https://mirrors.coreix.net/elrepo-archive-archive/kernel/el7/x86_64/RPMS/kernel-lt-headers-5.4.203-1.el7.elrepo.x86_64.rpm
  # 安装内核
  rpm -ivh kernel-lt-5.4.203-1.el7.elrepo.x86_64.rpm
  rpm -ivh kernel-lt-devel-5.4.203-1.el7.elrepo.x86_64.rpm

  # 设置 GRUB 默认启动新内核
  # 查看现有内核启动顺序
  awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg
  # 查看默认内核
  grubby --default-kernel
  # 查看启动内核
  cat /etc/grub2.cfg | grep menuentry|awk -F "\'" '$1=="menuentry " {print i++ " : " $2}'
  # 设置默认启动项（将0替换为上面命令输出的新内核位置）
  grub2-set-default 0
  # 查看默认内核
  grubby --default-kernel
  cat /etc/default/grub
  # 生成新的grub配置
  grub2-mkconfig -o /boot/grub2/grub.cfg
  # 重启生效
  reboot
  # 删除3.10内核版本（可选）
  yum remove -y kernel-3.10.0
  # 查看安装的kernel rpm 包
  rpm -qa | grep kernel
  # 安装内核依赖
  yum install -y gcc gcc-c++ glibc-devel glibc-headers
}

# 封装一个计时器函数
run_with_timer() {
    local function_name=$1
    local start_time=$(date +%s.%N)

    echo -e "\n Starting function: $function_name at $(date -d @$start_time)"

    # 执行传入的函数
    "$@"

    local end_time=$(date +%s.%N)
    local elapsed_time=$(echo "$end_time - $start_time" | bc)

    echo "Function $function_name finished at $(date -d @$end_time)"
    echo "Execution time: ${elapsed_time} seconds"
}

# finish tips
function finish_tips() {
  echo -e "\n >>>> finish tips"
  echo "======================================================"
  echo "系统初始化完成！"
  echo "需要注意以下事项："
  echo "1. SELinux配置变更需要重启生效"
  echo "2. 当前防火墙已关闭（生产环境请谨慎）"
  echo "3. 建议立即执行以下命令刷新环境：source /etc/profile"
  echo "4. 建议根据需要重启系统"
  echo "======================================================"
}

# 先配置yum 源再升级内核版本，后面的环节可以一次型执行，升级内核建议手动处理
function main() {
    # 配置域名服务器解析(可选)
    #config_dns_resolv
    # 检查网络连通性，需要连接外网
    run_with_timer check_internet_connection
    # 检查 Linux CentOS操作系统主版本
    run_with_timer check
    # 关闭 SELinux
    run_with_timer close_SELinux
    # 配置yum 源
    run_with_timer config_yum
    # 先升级内核版本至5.4 lt，再安装基础常用工具,这里需要reboot 重启,建议手动安装
    #run_with_timer upgrade_kernel_version
    # 安装常用工具
    #run_with_timer install_common_tools
    # 时间同步配置
    #run_with_timer time_chronyd
    # 关闭防火墙(可选)
    #run_with_timer close_firewalld
    # 优化系统参数
    #run_with_timer optimize_system_parameters
    # 设置文件打开数限制
    #run_with_timer update_files_limits
    # 修改终端时间显示
    #update_PS1
    # 关闭不常用的服务
    #run_with_timer close_uncommon_used_service

    # 完成提示
    #run_with_timer finish_tips
    # 重启系统生效(可选)
    # reboot
}

run_with_timer main

